//package com.example.springbootdemo.aop;
//
//import com.example.springbootdemo.annotation.Logging;
//import com.example.springbootdemo.enums.logging.LogLevelEnum;
//import com.example.springbootdemo.enums.logging.LogPrintEnum;
//import com.example.springbootdemo.enums.logging.LogSaveTypeEnum;
//import com.example.springbootdemo.util.CommonUtil;
//import org.apache.shiro.SecurityUtils;
//import org.apache.shiro.subject.Subject;
//import org.aspectj.lang.JoinPoint;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.*;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//
//import javax.servlet.http.HttpServletRequest;
//import java.io.PrintWriter;
//import java.io.StringWriter;
//import java.lang.reflect.Method;
//import java.text.SimpleDateFormat;
//import java.util.Arrays;
//import java.util.Date;
//import java.util.logging.LogRecord;
//
//
///**
// * 日志记录
// */
//
//@Aspect
//@Component
//public class LoggingAspect {
//
//    @Autowired
//    private LogRecordService logRecordService;
//
//    /**
//     * 执行时开始时间
//     */
//    private static long START_TIMEMILLIS = 0L;
//
//    @Pointcut("@annotation(com.hzyl.admin.annotation.Logging)")
//    public void annotationPointCut() {
//    }
//
//    @Before("annotationPointCut()")
//    public void before() {
//        START_TIMEMILLIS = System.currentTimeMillis();
//    }
//
//    @Around("annotationPointCut()")
//    public Object advice(ProceedingJoinPoint joinPoint) throws Throwable {
//        return joinPoint.proceed();
//    }
//
//    @After("annotationPointCut()")
//    public void after(JoinPoint joinPoint) {
//    }
//
//    /**
//     * 方法正常执行结束后的日志记录
//     *
//     * @param joinPoint
//     * @param retmsg    方法的返回值
//     */
//    @AfterReturning(value = "annotationPointCut()", returning = "retmsg")
//    public void afterReturning(JoinPoint joinPoint, Object retmsg) {
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        Subject subject = SecurityUtils.getSubject();
//        SystemUser systemUser = (SystemUser) subject.getPrincipal();
//
//        // 方法执行结束时间
//        long endTime = System.currentTimeMillis();
//
//        MethodSignature sign = (MethodSignature) joinPoint.getSignature();
//        Method method = sign.getMethod();
//        // 获取类名
//        Class<?> thisClass = joinPoint.getTarget().getClass();
//        // 获取方法名
//        String functionName = method.getName();
//
//        String formalKey = "";
//        String formalValue = "";
//        // 获取方法的形参名
//        String[] formalKeyArray = sign.getParameterNames();
//        if (formalKeyArray.length != 0) {
//            // 获取参入的参数
//            Object[] formalValueArray = joinPoint.getArgs();
//            formalKey = Arrays.toString(formalKeyArray);
//            formalValue = Arrays.toString(formalValueArray);
//        }
//
//        // 获取注解里的参数信息
//        Logging annotation = method.getAnnotation(Logging.class);
//        LogLevelEnum logLevel = annotation.logLevel();
//        LogSaveTypeEnum logSaveType = annotation.logSaveType();
//        String logTitle = annotation.logTitle();
//        String logDesc = annotation.logDesc();
//        LogPrintEnum logPrintEnum = annotation.printRetMsg();
//        // 获取返回值类型
//        Class<?> returnType = method.getReturnType();
//
//        // 获取日志需保存的地方
//        switch (logSaveType) {
//            case ALL:
//                saveDatabases(LogLevelEnum.INFO.toString(), logTitle, logLevel, logDesc, thisClass, functionName, formalValue, systemUser, START_TIMEMILLIS, endTime, request, "");
//                saveFile(logLevel, logPrintEnum, thisClass, functionName, logTitle, logDesc, START_TIMEMILLIS, endTime, formalKey, formalValue, returnType, retmsg, systemUser, request);
//                break;
//            case FILE:
//                saveFile(logLevel, logPrintEnum, thisClass, functionName, logTitle, logDesc, START_TIMEMILLIS, endTime, formalKey, formalValue, returnType, retmsg, systemUser, request);
//                break;
//            case DATABASE:
//                saveDatabases(LogLevelEnum.INFO.toString(), logTitle, logLevel, logDesc, thisClass, functionName, formalValue, systemUser, START_TIMEMILLIS, endTime, request, "");
//                break;
//            default:
//                break;
//        }
//    }
//
//    /**
//     * 执行方法时代码异常后的日志记录
//     *
//     * @param joinPoint
//     * @param ex
//     */
//    @AfterThrowing(value = "annotationPointCut()", throwing = "ex")
//    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        Subject subject = SecurityUtils.getSubject();
//        SystemUser systemUser = (SystemUser) subject.getPrincipal();
//
//        // 方法执行结束时间
//        long endTime = System.currentTimeMillis();
//
//        MethodSignature sign = (MethodSignature) joinPoint.getSignature();
//        Method method = sign.getMethod();
//        // 获取类名
//        Class<?> thisClass = joinPoint.getTarget().getClass();
//        // 获取方法名
//        String functionName = method.getName();
//
//        String formalKey = "";
//        String formalValue = "";
//        // 获取方法的形参名
//        String[] formalKeyArray = sign.getParameterNames();
//        if (formalKeyArray.length != 0) {
//            // 获取参入的参数
//            Object[] formalValueArray = joinPoint.getArgs();
//            formalKey = Arrays.toString(formalKeyArray);
//            formalValue = Arrays.toString(formalValueArray);
//        }
//
//        // 获取注解里的参数信息
//        Logging annotation = method.getAnnotation(Logging.class);
//        LogLevelEnum logLevel = annotation.logLevel();
//        LogSaveTypeEnum logSaveType = annotation.logSaveType();
//        String logTitle = annotation.logTitle();
//        String logDesc = annotation.logDesc();
//        LogPrintEnum logPrintEnum = annotation.printRetMsg();
//        // 获取返回值类型
//        Class<?> returnType = method.getReturnType();
//
//        // 获取日志需保存的地方
//        final Logger logger = LoggerFactory.getLogger(thisClass);
//
//        StringWriter sw = new StringWriter();
//        PrintWriter pw = new PrintWriter(sw);
//        ex.printStackTrace(pw);
//        String msg = sw.toString();
//        switch (logSaveType) {
//            case ALL:
//                logger.error(
//                        "执行目标:" + thisClass.toString() + SYMBOL_POINT + functionName + ", 执行时程序异常,详情如下:" + NEW_LINE +
//                                "方法名:" + logTitle + NEW_LINE +
//                                "方法描述:" + logDesc + NEW_LINE +
//                                "方法执行所跟踪到信息如下:" + NEW_LINE +
//                                "开始时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(START_TIMEMILLIS) + NEW_LINE +
//                                "结束时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(endTime) + NEW_LINE +
//                                "所用时间(毫秒):" + (endTime - START_TIMEMILLIS) + NEW_LINE +
//                                "方法所定义的参数名:" + formalKey + NEW_LINE +
//                                "调用者所传入的值为:" + formalValue + NEW_LINE +
//                                "方法的返回值类型为:" + returnType + NEW_LINE +
//                                "客户端信息如下:" + NEW_LINE +
//                                "方法执行者:" + (systemUser == null ? "游客[未登录用户]" : systemUser.getUsername()) + NEW_LINE +
//                                "IP地址:" + new CommonUtil().getRemoteHost(request) + NEW_LINE +
//                                "异常详情如下:", ex
//                );
//                saveDatabases(LogLevelEnum.ERROR.toString(), logTitle, LogLevelEnum.ERROR, ex.toString(), thisClass, functionName, formalValue, systemUser, START_TIMEMILLIS, endTime, request, msg);
//                break;
//            case FILE:
//                logger.error(
//                        "执行目标:" + thisClass.toString() + SYMBOL_POINT + functionName + ", 执行时程序异常,详情如下:" + NEW_LINE +
//                                "方法名:" + logTitle + NEW_LINE +
//                                "方法描述:" + logDesc + NEW_LINE +
//                                "方法执行所跟踪到信息如下:" + NEW_LINE +
//                                "开始时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(START_TIMEMILLIS) + NEW_LINE +
//                                "结束时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(endTime) + NEW_LINE +
//                                "所用时间(毫秒):" + (endTime - START_TIMEMILLIS) + NEW_LINE +
//                                "方法所定义的参数名:" + formalKey + NEW_LINE +
//                                "调用者所传入的值为:" + formalValue + NEW_LINE +
//                                "方法的返回值类型为:" + returnType + NEW_LINE +
//                                "客户端信息如下:" + NEW_LINE +
//                                "方法执行者:" + (systemUser == null ? "游客[未登录用户]" : systemUser.getUsername()) + NEW_LINE +
//                                "IP地址:" + new CommonUtil().getRemoteHost(request) + NEW_LINE +
//                                "异常详情如下:", ex
//                );
//                break;
//            case DATABASE:
//                saveDatabases(LogLevelEnum.ERROR.toString(), logTitle, LogLevelEnum.ERROR, ex.toString(), thisClass, functionName, formalValue, systemUser, START_TIMEMILLIS, endTime, request, msg);
//                break;
//            default:
//                break;
//        }
//    }
//
//    public void saveFile(LogLevelEnum logLevel, LogPrintEnum logPrintEnum, Class<?> thisClass, String functionName, String logTitle, String logDesc, long beginTime, long endTime,
//                         String formalKey, String formalValue, Class<?> returnType, Object retmsg, SystemUser systemUser, HttpServletRequest request) {
//        final Logger logger = LoggerFactory.getLogger(thisClass);
//        switch (logLevel) {
//            case ERROR:
//                logger.error(logDetails(
//                        logPrintEnum,
//                        thisClass.toString(),
//                        functionName,
//                        logTitle,
//                        logDesc,
//                        START_TIMEMILLIS,
//                        endTime,
//                        formalKey,
//                        formalValue,
//                        returnType.toString(),
//                        retmsg.toString(),
//                        systemUser == null ? "游客[未登录用户]" : systemUser.getUsername(),
//                        request
//                ));
//                break;
//            case WARN:
//                logger.warn(logDetails(
//                        logPrintEnum,
//                        thisClass.toString(),
//                        functionName,
//                        logTitle,
//                        logDesc,
//                        START_TIMEMILLIS,
//                        endTime,
//                        formalKey,
//                        formalValue,
//                        returnType.toString(),
//                        retmsg.toString(),
//                        systemUser == null ? "游客[未登录用户]" : systemUser.getUsername(),
//                        request
//                ));
//                break;
//            case INFO:
//                logger.info(logDetails(
//                        logPrintEnum,
//                        thisClass.toString(),
//                        functionName,
//                        logTitle,
//                        logDesc,
//                        START_TIMEMILLIS,
//                        endTime,
//                        formalKey,
//                        formalValue,
//                        returnType.toString(),
//                        retmsg.toString(),
//                        systemUser == null ? "游客[未登录用户]" : systemUser.getUsername(),
//                        request
//                ));
//                break;
//            case DEBUG:
//                logger.debug(logDetails(
//                        logPrintEnum,
//                        thisClass.toString(),
//                        functionName,
//                        logTitle,
//                        logDesc,
//                        START_TIMEMILLIS,
//                        endTime,
//                        formalKey,
//                        formalValue,
//                        returnType.toString(),
//                        retmsg.toString(),
//                        systemUser == null ? "游客[未登录用户]" : systemUser.getUsername(),
//                        request
//                ));
//                break;
//            case TRACE:
//                logger.trace(logDetails(
//                        logPrintEnum,
//                        thisClass.toString(),
//                        functionName,
//                        logTitle,
//                        logDesc,
//                        START_TIMEMILLIS,
//                        endTime,
//                        formalKey,
//                        formalValue,
//                        returnType.toString(),
//                        retmsg.toString(),
//                        systemUser == null ? "游客[未登录用户]" : systemUser.getUsername(),
//                        request
//                ));
//                break;
//            default:
//                break;
//        }
//    }
//
//    public static String logDetails(LogPrintEnum logPrintEnum, String className, String functionName, String logTitle, String logDesc, long beginTime, long endTime,
//                                    String formalKey, String formalValue, String returnType, String retmsg, String username, HttpServletRequest request) {
//        switch (logPrintEnum) {
//            case REM_RETURN_MSG:
//                return "执行目标:" + className + SYMBOL_POINT + functionName + NEW_LINE +
//                        "方法名:" + logTitle + NEW_LINE +
//                        "方法描述:" + logDesc + NEW_LINE +
//                        "方法执行所跟踪到信息如下:" + NEW_LINE +
//                        "开始时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(beginTime) + NEW_LINE +
//                        "结束时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(endTime) + NEW_LINE +
//                        "所用时间(毫秒):" + (endTime - beginTime) + NEW_LINE +
//                        "方法所定义的参数名:" + formalKey + NEW_LINE +
//                        "调用者所传入的值为:" + formalValue + NEW_LINE +
//                        "方法的返回值类型为:" + returnType + NEW_LINE +
//                        "客户端信息如下:" + NEW_LINE +
//                        "方法执行者:" + username + NEW_LINE +
//                        "IP地址:" + new CommonUtil().getRemoteHost(request);
//            default:
//                return "执行目标:" + className + SYMBOL_POINT + functionName + NEW_LINE +
//                        "方法名:" + logTitle + NEW_LINE +
//                        "方法描述:" + logDesc + NEW_LINE +
//                        "方法执行所跟踪到信息如下:" + NEW_LINE +
//                        "开始时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(beginTime) + NEW_LINE +
//                        "结束时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(endTime) + NEW_LINE +
//                        "所用时间(毫秒):" + (endTime - beginTime) + NEW_LINE +
//                        "方法所定义的参数名:" + formalKey + NEW_LINE +
//                        "调用者所传入的值为:" + formalValue + NEW_LINE +
//                        "方法的返回值类型为:" + returnType + NEW_LINE +
//                        "所返回的数据为:" + retmsg + NEW_LINE +
//                        "客户端信息如下:" + NEW_LINE +
//                        "方法执行者:" + username + NEW_LINE +
//                        "IP地址:" + new CommonUtil().getRemoteHost(request);
//        }
//    }
//
//
//    public boolean saveDatabases(String logType, String logTitle, LogLevelEnum logLevel, String logDesc, Class<?> thisClass, String functionName, String formal, SystemUser systemUser,
//                                 long beginTime, long endTime, HttpServletRequest request, String details) {
//        LogRecord logRecord = new LogRecord();
//        logRecord.setType(logType);
//        logRecord.setLevel(logLevel.toString());
//        logRecord.setTitle(logTitle);
//        logRecord.setDesc(logDesc);
//        logRecord.setClassPath(thisClass.toString() + SYMBOL_POINT + functionName + "(" + formal + ")");
//        logRecord.setExecutor(systemUser == null ? "游客[未登录用户]" : systemUser.getUsername());
//        logRecord.setIpAddress(new CommonUtil().getRemoteHost(request));
//        logRecord.setBeginTime(new Date(beginTime));
//        logRecord.setEndTime(new Date(endTime));
//        logRecord.setDetails(details);
//        return logRecordService.insert(logRecord);
//    }
//}
